/*
 * the modules buffer list test demo
 */

#include "session.h"

#define PUT_STR1 "### module 1 data A ###"
#define PUT_STR2 "@@@ module 2 data B @@@"
#define PUT_STR3 "*** module 3 data C ***"

int main()
{
	struct SESSION buffer_group;
	struct SESSION buffer_group2;
	psysbuf_t buf;
	psysbuf_t buf2;
    psysbuf_t load_buf = NULL;
    psysbuf_t load_buf_bak = NULL;
	session_buffer_t *sbf;
	int i = 0;

	//////// init ////////
    /* init buffer first */
	printf("\n\nList buffer all group init\n");
	sysbuf_init();
	sysbuf_reset(SYSBUF_GROUP_DATBUFS);

	/* module 1 and module 2 buffer init */
	printf("Modules buffer init\n\n");
	SessionInitAll();
	SessionBufferInit(&buffer_group);
	SessionBufferInit(&buffer_group2);

	do {
		/******* one data test *******/
		printf("******** ONE DATA TEST ********\n");
		/* module1 put data */
		printf(">>>Module1 put data A\n");
		buf = sysbuf_alloc(SYSBUF_GROUP_DATBUFS);
		if (buf == NULL)
			return 0;

		memcpy((void *)(buf->haddr + buf->size), PUT_STR1, sizeof(PUT_STR1));
		buf->size = sizeof(PUT_STR1);
		sbf = SessionBufferPush(&buffer_group2, buf);
		if (sbf == NULL)
			sysbuf_free(buf);

		/* module2 get data */
		printf("____________Module2 get one data____________\n");
		load_buf = load_buf_bak;
		if (load_buf == NULL) {
			// can used for module buffer and never free
			load_buf = sysbuf_alloc(SYSBUF_GROUP_DATBUFS);
			load_buf_bak = load_buf;
		}

		if (SessionBufferTopNum(&buffer_group2) > 10) {
			// get the cache num
			return 0;
		}
		buf2 = SessionBufferPop(&buffer_group2);
		if (buf2) {
			if (buf2->list.group == load_buf->list.group) {
				// the same group use pointer
				load_buf = buf2;
			}
			else {
				// different grout should memcpy
				phys_addr_t src, dst;
				src = buf2->haddr + buf2->offset;
				dst = load_buf->haddr + load_buf->offset;
				memcpy((void *)dst, (void *)src, buf2->size);
				load_buf->size = buf2->size;
				if (buf2->flags & SYS_BUF_FLAG_EOF)
					load_buf->flags |= SYS_BUF_FLAG_EOF;
				load_buf->user = buf2->user;
				sysbuf_free(buf2);
			}
		}
		else {
			load_buf = NULL;
		}
		printf("<<<Module 2 get data: %s\n", (char *)load_buf->haddr);
		if (load_buf) {
			sysbuf_free(load_buf);
			load_buf = NULL;
		}
		if (load_buf_bak) {
			// can never free in running, and free it in the program end
			sysbuf_free(load_buf_bak);
			load_buf_bak = NULL;
		}

		/******* multi data test *******/
		printf("\n******** MULTI DATA TEST ********\n");
		printf(">>>Module1 put data A\n");
		buf = sysbuf_alloc(SYSBUF_GROUP_DATBUFS);
		memcpy((void *)(buf->haddr + buf->size), PUT_STR1, sizeof(PUT_STR1));
		buf->size = sizeof(PUT_STR1);
		SessionBufferPush(&buffer_group2, buf);
		sysbuf_free(buf);

		printf(">>>Module1 put data B\n");
		buf = sysbuf_alloc(SYSBUF_GROUP_DATBUFS);
		memcpy((void *)(buf->haddr + buf->size), PUT_STR2, sizeof(PUT_STR2));
		buf->size = sizeof(PUT_STR2);
		SessionBufferPush(&buffer_group2, buf);
		sysbuf_free(buf);

		printf(">>>Module1 put data C\n");
		buf = sysbuf_alloc(SYSBUF_GROUP_DATBUFS);
		memcpy((void *)(buf->haddr + buf->size), PUT_STR3, sizeof(PUT_STR3));
		buf->size = sizeof(PUT_STR3);
		SessionBufferPush(&buffer_group2, buf);
		sysbuf_free(buf);

		buf2 = SessionBufferPop(&buffer_group2);
		printf("<<<Module 2 get data: %s\n", (char *)buf2->haddr);
		sysbuf_free(buf2);
		buf2 = SessionBufferPop(&buffer_group2);
		printf("<<<Module 2 get data: %s\n", (char *)buf2->haddr);
		sysbuf_free(buf2);
		buf2 = SessionBufferPop(&buffer_group2);
		printf("<<<Module 2 get data: %s\n", (char *)buf2->haddr);
		sysbuf_free(buf2);

		printf("times: %d ", i++);
		for (int j = 0; j < i % 20; j++)
			printf("****");
		printf("\n");
		usleep(100 * 1000);
	} while (1);

	printf("\nModule buffer deinit\n\n\n");
	SessionBufferDeInit(&buffer_group);
	SessionBufferDeInit(&buffer_group2);

	return 0;
}
